import React, { useEffect, useRef } from 'react';
import { Icon } from 'antd';
import cn from 'classnames';
import PropTypes from 'prop-types';
import './NewTopology.less';

const elementIsShown = element => element.offsetWidth > 0 && element.offsetHeight > 0;

const NewTopology = ({ data, renderItem, renderLabel, labelKey, childrenKey, rightChildrenKey }) => {
    const topology = useRef(null);
    const render = (tree, level, parentNode) => tree.map(item => {
        const label = typeof labelKey === 'function' ? labelKey(item) : item[labelKey];
        const children = typeof childrenKey === 'function' ? childrenKey(item) : item[childrenKey];
        const rightChildren = typeof rightChildrenKey === 'function' ? rightChildrenKey(item) : item[rightChildrenKey];
        const hasChildren = children && children.length > 0;
        const hasRightChildren = rightChildren && rightChildren.length > 0;
        const onlyOneChild = children && children.length === 1;
        return (
            renderItem && typeof renderItem === 'function' ? renderItem(item) : (
                <div className="topology-item">
                    <div className="topology-label">
                        <div className="topology-label-wrap">
                            {renderLabel ? renderLabel(item) : label}
                            {parentNode && <div className="topology-top-line" />}
                            {hasChildren && <div className="topology-bottom-line" />}
                            {hasRightChildren && <div className="topology-right-line" /> }
                            {hasChildren && (
                                <Icon
                                    title="展开"
                                    className="topology-toggle-btn topology-bottom-expanded-btn"
                                    type="plus-circle"
                                    theme="twoTone"
                                    twoToneColor="#52c41a"
                                />
                            )}
                            {hasChildren && (
                                <Icon
                                    title="收起"
                                    className="topology-toggle-btn topology-bottom-collapsed-btn"
                                    type="minus-circle"
                                    theme="twoTone"
                                    twoToneColor="#52c41a"
                                />
                            )}
                            {hasRightChildren && (
                                <Icon
                                    title="展开"
                                    className="topology-toggle-btn-r topology-right-expanded-btn"
                                    type="plus-circle"
                                    theme="twoTone"
                                    twoToneColor="#52c41a"
                                />
                            )}
                            {hasRightChildren && (
                                <Icon
                                    title="收起"
                                    className="topology-toggle-btn-r topology-right-collapsed-btn"
                                    type="minus-circle"
                                    theme="twoTone"
                                    twoToneColor="#52c41a"
                                />
                            )}
                            {rightChildren && rightChildren.length > 0 && (
                                <div className="topology-right-children">
                                    {render(rightChildren, level + 1, item)}
                                </div>
                            )}
                        </div>
                    </div>
                    {hasChildren && (
                        <div className={cn('topology-children', {
                            'topology-only-one-children': onlyOneChild
                        })}>
                            {render(children, level + 1, item)}
                        </div>
                    )}
                </div>
            )
        )
    });
    useEffect(() => {
        // 计算topology-label高度，以使topology-right-children撑开，不会与底部重叠
        if (topology.current) {
            const rightChildren = topology.current.querySelectorAll('.topology-right-children');

            rightChildren.forEach(children => {
                if (elementIsShown(children)) {
                    const label = children.parentElement.parentElement;
                    const labelBound = label.getBoundingClientRect();
                    const childrenBound = children.getBoundingClientRect();
                    const labelWrap = children.parentElement;
                    const bottomLine = label.querySelector('.topology-bottom-line');
                    const labelMinHeight = childrenBound.bottom - labelBound.top;
                    const labelMinWidth = childrenBound.right - labelBound.right;
                    label.style.minHeight = `${labelMinHeight}px`;
                    const firstItem = children.firstElementChild;
                    if (firstItem) {
                        children.style.transform = `translateY(${-firstItem.offsetHeight + 1}px)`;
                    }
                    // 当 right-children 右边小于底部时才添加 padding-right
                    if (!label.nextElementSibling || (label.nextElementSibling &&
                        label.parentElement.getBoundingClientRect().right <
                        childrenBound.right)) {
                        label.parentElement.style.paddingRight = `${labelMinWidth}px`;
                    }
                    if (bottomLine) {
                        bottomLine.style.height = `${labelMinHeight - labelWrap.offsetHeight + 2}px`;
                    }
                }
            });
        }
    }, []);
    return (
        <div className="topology-box" ref={topology}>{render(data, 0)}</div>
    )
};

NewTopology.propTypes = {
    data: PropTypes.array,
    labelKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
    childrenKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
    rightChildrenKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
    renderItem: PropTypes.oneOfType([PropTypes.func, undefined]),
    renderLabel: PropTypes.oneOfType([PropTypes.func, undefined])
};

NewTopology.defaultProps = {
    data: [],
    labelKey: 'label',
    childrenKey: 'children',
    rightChildrenKey: 'rightChildren',
    renderItem: undefined,
    renderLabel: undefined
};

export default NewTopology;
